/*
 * Clock.cpp
 *
 *  Created on: Mar 3, 2010
 *      Author: dcrown
 */

#include "Clock.h"
#include "Logger.h"
#include <utility>

using namespace std;

const string START_MARK = "start";
const float MILLIS_PER_SEC = 1000.0;

void Clock::Start()
{
	//Logger::getInstance().LOG(Logger::DEBUG, "Clock 1");
	startTime = timeGetTime();
	//Logger::getInstance().LOG(Logger::DEBUG, "Clock 2");
	markMap.insert(pair<string, DWORD>(START_MARK, startTime));
	//Logger::getInstance().LOG(Logger::DEBUG, "Clock 3");
}


DWORD Clock::Mark(string id, MarkAction ma)
{
	//Logger::getInstance().LOG(Logger::DEBUG, "fuckthisshit");
	map<string, DWORD>::iterator it;
	it = markMap.find(id);

	//if the mark is not already present, or we are supposed to remove it
	//add update or add it and return current time
	if (it == markMap.end())
	{
		DWORD now = timeGetTime();
		markMap.insert(pair<string, DWORD>(id, now));
		return now;
	}
	else
	{
		switch (ma)
		{
			case LEAVE_MARK:
			{
				return it->second;
				break;
			}
			case REMOVE_MARK:
			case UPDATE_MARK:
			{
				markMap.erase(it);

				DWORD now = timeGetTime();
				markMap.insert(pair<string, DWORD>(id, now));
				return now;
			}
			default:
			{
				Logger::getInstance().LOG(Logger::RECOVERABLE, "Invalid attempt to add an already present mark: %s", id.c_str());
				return markMap.find(START_MARK)->second;
				break;
			}
		}
	}
}

DWORD Clock::GetTimeSinceMark(string id, MarkAction ma)
{
	map<string, DWORD>::iterator it;
	it = markMap.find(id);

	DWORD markedTime;
	DWORD now = timeGetTime();
	if (it != markMap.end())
	{
		markedTime = it->second;
		if (ma == UPDATE_MARK)
		{
			markMap.erase(it);
			markMap.insert(pair<string, DWORD>(id, now));
		}
		else if (ma == REMOVE_MARK)
		{
			markMap.erase(it);
		}
	}
	else
	{
		markedTime = markMap.find(START_MARK)->second;

		if (ma == UPDATE_MARK)
		{
			markMap.insert(pair<string, DWORD>(id, now));
		}
	}

	return now - markedTime;
}

float Clock::GetTimeSinceMarkInSec(string id, MarkAction ma)
{
	return (float)GetTimeSinceMark(id, ma)/MILLIS_PER_SEC;
}

float Clock::GetTimeInSec()
{
	return (float)GetTime()/MILLIS_PER_SEC;
}
